最開始我是在Windows 10的PC上安裝Docker,用來測試與學習,有很多已經安裝好的image,直接下載後就很快就可以架設好服務,十分方便。
我在Windows的Docker有下載一個image,並產生container,測試與操作上並沒有任何問題。後來我另外架設了一台Linux平台的Docker,並且將該image移轉到新平台上。
我用移轉過來的image產生新的container,參數都跟在Windows平台上一樣,也沒有什麼異常。
直到在這個container上執行 ls -lh的指令時,卻出現了下列的錯誤,在Windows平台上的container並無此錯誤,而且還是以root的身分。
root@3c68aa381e26# ls -lh
ls: cannot access 'prtg_uwsgi.sock': Operation not permitted
total 0
s????????? ? ? ? ? ? prtg_uwsgi.sock
在google查找一下原因,發現是Linux核心中有預設有開啟seccomp的緣故。所以不只是ls,還有許多的指令都會出現Operation not permitted
seccomp(secure computing mode,安全計算模式)可以用來限制容器內可用的操作。
預設的seccomp配置為容器提供了一個合理的設定,並且禁用許多的系統呼叫。它具有適度的保護性,同時提供廣泛的應用相容性。
更詳給的內容可以參考:https://docs.docker.com/engine/security/seccomp/
為了讓Docker更加安全,所以限制了container部份的權限,就算是以root身份來執行,該限制依舊是有效的。
檢查系統是否有支援secomp,我的系統上是有支援的:
# cat /boot/config-$(uname -r) |grep CONFIG_SECCOMP
CONFIG_SECCOMP=y
但是我的應用程式需要一個被限制住的功能--修改系統時間,才在正常執行,所以有幾種方式可以放寬限制:
1、使用privileged來啟用特權容器(privileged container),即可取得最大的權限
# docker run --privileged <image>
2、關閉seccomp
docker run --security-opt seccomp=unconfined <image>
3、放寬部份的限制,這是建議的方式,只開放有需要的權限,可參考https://docs.docker.com/engine/security/seccomp/
例如文件中關於修改系統時間的說明如下:
settimeofday Time/date is not namespaced. Also gated by CAP_SYS_TIME.
stime Time/date is not namespaced. Also gated by CAP_SYS_TIME.
我們就可以將CAP_SYS_TIME加入白名單中,以解除此限制(會自動加上cap_,所以只需要指定sys_timem關鍵字),如下所示:
# docker run --cap-add SYS_TIME <image>
最終我選擇了方法3,只開放有需要的權限,這樣問題就解決了。